package com.oneonefive.educationsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oneonefive.educationsystem.domain.*;
import com.oneonefive.educationsystem.dto.Result;
import com.oneonefive.educationsystem.mapper.ArrangeMapper;
import com.oneonefive.educationsystem.mapper.StudentMapper;
import com.oneonefive.educationsystem.service.*;
import com.oneonefive.educationsystem.utils.Constant;
import com.oneonefive.educationsystem.utils.StateChangeUtil;
import com.oneonefive.educationsystem.vo.ArrangeVo;
import com.oneonefive.educationsystem.vo.SemesterVo;
import com.oneonefive.educationsystem.vo.StudentRequestVo;
import io.netty.util.internal.StringUtil;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

@Service
public class ArrangeServiceImpl extends ServiceImpl<ArrangeMapper, Arrange> implements ArrangeService {

    @Resource
    ArrangeMapper arrangeMapper;

    @Resource
    SemesterService semesterService;
    @Resource
    LabService labService;

    @Resource
    TeacherRequestService teacherRequestService;

    @Resource
    StudentRequestService studentRequestService;

    @Resource
    StudentMapper studentMapper;

    @Resource
    StudentService studentService;

    @Override
    public Result arrangeList(String term) {
        List<Arrange> arranges;
        if (!StringUtil.isNullOrEmpty(term)) {
            SemesterVo semester = new SemesterVo();
            semester.setTerm(term);
            Result result = semesterService.semesterList(semester);
            List<Semester> semester1 = (List<Semester>) result.getData();
            if (semester1.size() == 0) {
                return Result.fail("输入的学期不存在");
            } else if (semester1.size() > 1) {
                return Result.fail("输入的学期存在多个");
            }
            arranges = arrangeMapper.arrangeList(semester1.get(0));
        } else {
            //获取公共排课表
            arranges = arrangeMapper.arrangeList(Constant.SEMESTER);
        }
        int size = arranges.size();
        //创建安排排课的LinkedList，并加上星期一~星期五
        List<ArrangeVo> voList = new LinkedList<>();
        //定义一个index，为公共排课表arranges的索引。从0开始
        int index=0;
        //对星期一到五遍历
        for (int i = 1; i <= 5; i++) {
            boolean flag = false;
            while (index < size && arranges.get(index).getWeekday() == i) {
                flag = true;
                Arrange curArrange = arranges.get(index);
                ArrangeVo arrangeVo = new ArrangeVo();
                BeanUtils.copyProperties(arranges.get(index), arrangeVo);
                if (index == 0) {
                    voList.add(arrangeVo);
                    voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                } else {
                    Arrange preArrange = arranges.get(index - 1);
                    if (Objects.equals(preArrange.getWeekday(), curArrange.getWeekday())
                            && Objects.equals(preArrange.getTeacherRequest().getLabType(), curArrange.getTeacherRequest().getLabType())
                            && Objects.equals(preArrange.getLabId(), curArrange.getLabId())) {
                        if (voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] == null) {

                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                        } else {
                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] += "------\n" + getTeaContent(curArrange);
                        }
                    } else {
                        voList.add(arrangeVo);
                        voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                    }
                }
                index++;
            }
            if (!flag) {
                ArrangeVo arrangeVo = new ArrangeVo();
                arrangeVo.setWeekday(i);
                voList.add(arrangeVo);
            }
        }
        getResVo(voList);
        voList.sort(new ArrangeVo());
        long len = voList.size();
        return Result.ok(voList, len);
    }


    @Override
    public Result teaArrange(Integer trId) {
        //获取指定类型的实验室
        //--------------
        TeacherRequest teacherRequest = teacherRequestService.getById(trId);
        List<Lab> typeList = (List<Lab>) labService.getTypeList(teacherRequest.getLabType()).getData();
        String term = teacherRequest.getTerm();
        List<Arrange> arranges;
        if (!StringUtil.isNullOrEmpty(term)) {
            SemesterVo semester = new SemesterVo();
            semester.setTerm(term);
            Result result = semesterService.semesterList(semester);
            List<Semester> semester1 = (List<Semester>) result.getData();
            if (semester1.size() == 0) {
                return Result.fail("输入的学期不存在");
            } else if (semester1.size() > 1) {
                return Result.fail("输入的学期存在多个");
            }
            arranges = arrangeMapper.teaArrangeList(semester1.get(0),teacherRequest.getSection());
        } else {
            //获取公共排课表
            arranges = arrangeMapper.teaArrangeList(Constant.SEMESTER,teacherRequest.getSection());
        }

        int size = arranges.size();
        //创建安排排课的LinkedList，并加上星期一~星期五
        List<ArrangeVo> voList = new ArrayList<>();
        //定义一个index，为公共排课表arranges的索引。从0开始
        int index=0;
        //对星期一到五遍历
        for (int i = 1; i <= 5; i++) {
            //temp是指定类型实验室id，用来删除不需要的实验室id，同时不会影响完整的指定类型的实验室
            List<Lab> temp = new ArrayList<>(typeList);
                while (index < size && arranges.get(index).getWeekday() == i) {
                Arrange curArrange = arranges.get(index);
                    if (temp.contains(curArrange.getLab())) {
                        boolean flag = false;

                        for (int x = index + 1; x < arranges.size(); x++) {
                            if ((Objects.equals(curArrange.getLabId(), arranges.get(x).getLabId())
                                &&Objects.equals(curArrange.getWeekday(),arranges.get(x).getWeekday())
                            &&Objects.equals(curArrange.getTeacherRequest().getSection(),arranges.get(x).getTeacherRequest().getSection()))) {
                                flag = true;
                                break;
                            }
                        }
                        if (!flag) {
                            temp.remove(curArrange.getLab());
                        }
                        ArrangeVo arrangeVo = new ArrangeVo();
                        BeanUtils.copyProperties(arranges.get(index), arrangeVo);
                        if (index == 0) {
                            if (teaCheckCanChoose(arrangeVo, teacherRequest)) {
                                arrangeVo.setState(true);
                                System.out.println(i + "：不可以选！！！！！！！！");
                            }
                            voList.add(arrangeVo);
                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().
                                    getSection()] = getTeaContent(curArrange);
                        } else {
                            Arrange preArrange = arranges.get(index - 1);
                            if (Objects.equals(preArrange.getWeekday(), curArrange.getWeekday())
                                    && Objects.equals(preArrange.getTeacherRequest().getLabType(), curArrange.getTeacherRequest().getLabType())
                                    && Objects.equals(preArrange.getLabId(), curArrange.getLabId())) {
                                checkNull(voList, curArrange);
                                if (teaCheckCanChoose(arrangeVo, teacherRequest)) {
                                    arrangeVo.setState(true);
                                    System.out.println(i + "：不可以选！！！！！！！！");
                                }
                            } else {
                                if (teaCheckCanChoose(arrangeVo, teacherRequest)) {
                                    arrangeVo.setState(true);
                                    System.out.println(i + "：不可以选！！！！！！！！");
                                }
                                voList.add(arrangeVo);
                                voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                            }

                        }
                    }
                index++;
            }
            teaAddNotClassLab(voList, temp, i);

        }

        getResVo(voList);
        long len = voList.size();
        voList.sort(new ArrangeVo());
        return Result.ok(voList, len);
    }


    @Override
    public Result stuArrange(String srId) {
        //获取指定类型的实验室
        //--------------
        StudentRequest studentRequest = studentRequestService.getById(srId);
        String labId = studentRequest.getLabId();
        Lab lab = (Lab) labService.getByLabId(labId).getData();
        String term = studentRequest.getTerm();
        List<Arrange> arranges;
        if (!StringUtil.isNullOrEmpty(term)) {
            SemesterVo semester = new SemesterVo();
            semester.setTerm(term);
            Result result = semesterService.semesterList(semester);
            List<Semester> semester1 = (List<Semester>) result.getData();
            if (semester1.size() == 0) {
                return Result.fail("输入的学期不存在");
            } else if (semester1.size() > 1) {
                return Result.fail("输入的学期存在多个");
            }
            arranges = arrangeMapper.stuArrangeList(semester1.get(0), labId,studentRequest.getWeek(),studentRequest.getSection());
        } else {
            //获取公共排课表
            arranges = arrangeMapper.stuArrangeList(Constant.SEMESTER, labId,studentRequest.getWeek(),studentRequest.getSection());
        }

        //获取可能会冲突的学生排课
        StudentRequestVo studentRequestVo = new StudentRequestVo();
        studentRequestVo.setTerm(studentRequest.getTerm());
        studentRequestVo.setSection(studentRequest.getSection());
        studentRequestVo.setLabId(studentRequest.getLabId());
        studentRequestVo.setState(1);
        studentRequestVo.setWeek(studentRequest.getWeek());
        List<StudentRequest> studentRequestList = (List<StudentRequest>) studentRequestService.stuReqList(studentRequestVo).getData();

        //------------------------
        int size = arranges.size();
        //创建安排排课的LinkedList，并加上星期一~星期五
        List<ArrangeVo> voList = new LinkedList<>();

        //定义一个index，为公共排课表arranges的索引。从0开始
        int index = 0;
        //对星期一到五遍历
        for (int i = 1; i <= 5; i++) {
            boolean flag = false;
            while (index < size && arranges.get(index).getWeekday() == i) {
                flag = true;
                Arrange curArrange = arranges.get(index);
                if (labId.equals(curArrange.getLabId())) {
                    ArrangeVo arrangeVo = new ArrangeVo();
                    BeanUtils.copyProperties(arranges.get(index), arrangeVo);
                    if (index == 0) {
                        voList.add(arrangeVo);
                        voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                    } else {
                        Arrange preArrange = arranges.get(index - 1);
                        if (Objects.equals(preArrange.getWeekday(), curArrange.getWeekday())
                                && Objects.equals(preArrange.getTeacherRequest().getLabType(), curArrange.getTeacherRequest().getLabType())
                                && Objects.equals(preArrange.getLabId(), curArrange.getLabId())) {
                            checkNull(voList, curArrange);
                        } else {
                            voList.add(arrangeVo);
                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                        }
                    }
                }
                index++;
            }
            System.out.println("星期" + i);
            if (!flag) {
                System.out.println("未被老师占用");
                StudentRequest s = null;
                int len = studentRequestList.size();
                for (int x = len - 1; x >= 0; x--) {
                    if (studentRequestList.get(x).getWeekday() == i) {
                        System.out.println("被学生占用");
                        s = studentRequestList.get(x);
                        studentRequestList.remove(studentRequestList.get(x));
                        stuAddReqClass(voList, s, i);
                        break;
                    }
                }
                if (s == null) {
                    stuAddNOTClassLab(voList,lab,i);
                }
            }
        }
        getResVo(voList);
        voList.sort(new ArrangeVo());
        long len = voList.size();
        return Result.ok(voList, len);

    }

    private void checkNull(List<ArrangeVo> voList, Arrange curArrange) {
        if (voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] == null) {
            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
        } else {
            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] += getTeaContent(curArrange);
        }
    }


    @Override
    public Result listSave(List<Arrange> arrangeList) {
        int trId = arrangeList.get(0).getTrId();
        TeacherRequest teacherRequest = teacherRequestService.getById(trId);
        int stuNum = teacherRequest.getStuNum();
        int equipment = 0;
        for (Arrange arrange : arrangeList) {
            Lab lab = (Lab) labService.getByLabId(arrange.getLabId()).getData();
            equipment += lab.getEquipment();
        }
        if (stuNum > equipment) {
            return Result.fail("选中实验室的总设备数小于班级学生人数");
        }
        for (Arrange arrange : arrangeList) {
            save(arrange);
        }
        return Result.ok("arrange保存成功");
    }

    @Override
    public Result listUpdate(List<Arrange> arrangeList) {
        int trId = arrangeList.get(0).getTrId();
        QueryWrapper<Arrange> wrapper = new QueryWrapper<>();
        wrapper.eq("tr_id", trId);
        boolean remove = remove(wrapper);
        if (!remove) {
            return Result.fail("删除旧数据失败");
        }
        return listSave(arrangeList);
    }

    @Override
    public Result clazzArrange(String term, User user) {
        QueryWrapper<Student> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", user.getUserId());
        Student student = studentService.getOne(wrapper);
        List<Arrange> arranges;
        if (!StringUtil.isNullOrEmpty(term)) {
            SemesterVo semester = new SemesterVo();
            semester.setTerm(term);
            Result result = semesterService.semesterList(semester);
            List<Semester> semester1 = (List<Semester>) result.getData();
            if (semester1.size() == 0) {
                return Result.fail("输入的学期不存在");
            } else if (semester1.size() > 1) {
                return Result.fail("输入的学期存在多个");
            }
            System.out.println(student.getClazz());
            arranges = arrangeMapper.clazzArrangeList(semester1.get(0),student.getClazz());
        } else {
            //获取公共排课表
            arranges = arrangeMapper.clazzArrangeList(Constant.SEMESTER,student.getClazz());
        }
        int size = arranges.size();
        //创建安排排课的LinkedList，并加上星期一~星期五
        List<ArrangeVo> voList = new LinkedList<>();
        //定义一个index，为公共排课表arranges的索引。从0开始
        int index=0;
        //对星期一到五遍历
        for (int i = 1; i <= 5; i++) {
            boolean flag = false;
            //temp是指定类型实验室id，用来删除不需要的实验室id，同时不会影响完整的指定类型的实验室
            while (index < size && arranges.get(index).getWeekday() == i) {
                flag = true;
                Arrange curArrange = arranges.get(index);
                ArrangeVo arrangeVo = new ArrangeVo();
                BeanUtils.copyProperties(arranges.get(index), arrangeVo);
                if (index == 0) {
                    voList.add(arrangeVo);
                    voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                } else {
                    Arrange preArrange = arranges.get(index - 1);
                    if (Objects.equals(preArrange.getWeekday(), curArrange.getWeekday())
                            && Objects.equals(preArrange.getTeacherRequest().getLabType(), curArrange.getTeacherRequest().getLabType())
                            && Objects.equals(preArrange.getLabId(), curArrange.getLabId())) {
                        if (voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] == null) {

                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                        } else {
                            voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] += "------\n" + getTeaContent(curArrange);
                        }
                    } else {
                        voList.add(arrangeVo);
                        voList.get(voList.size() - 1).getStrings()[curArrange.getTeacherRequest().getSection()] = getTeaContent(curArrange);
                    }
                }
                index++;
            }
            if (!flag) {
                ArrangeVo arrangeVo = new ArrangeVo();
                arrangeVo.setWeekday(i);
                voList.add(arrangeVo);
            }
        }
        getResVo(voList);
        voList.sort(new ArrangeVo());
        long len = voList.size();
        return Result.ok(voList, len);
    }

    private boolean teaCheckCanChoose(ArrangeVo arrangeVo, TeacherRequest teacherRequest) {
        TeacherRequest exist = arrangeVo.getTeacherRequest();
           if (!Objects.equals(exist.getSection(), teacherRequest.getSection())
                || !Objects.equals(exist.getLabType(), teacherRequest.getLabType())) {
            return true;
        }
        return exist.getStartWeek() <= teacherRequest.getEndWeek() && exist.getEndWeek() >= teacherRequest.getStartWeek();
    }


    public String getTeaContent(Arrange arrange) {
        return "课程:" + arrange.getTeacherRequest().getLessonName()
                + "\n教师:" + arrange.getUser().getName()
                + "\n班级:" + arrange.getTeacherRequest().getStuClass()
                + "\n周次:" + arrange.getTeacherRequest().getStartWeek() + "~" + arrange.getTeacherRequest().getEndWeek()+"\n";
    }

    private String getStuContent(StudentRequest s) {
        QueryWrapper<Student> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", s.getUserId());
        Student student = studentMapper.selectOne(wrapper);
        return "学生:" + s.getUser().getName()
                + "\n班级:" + student.getClazz()
                +"\n周次:"+s.getWeek()+"\n";
    }


    public void getResVo(List<ArrangeVo> list) {
        for (ArrangeVo arrangeVo : list) {
            arrangeVo.setWeekdayString(StateChangeUtil.weekdayChange(arrangeVo.getWeekday()));
        }
    }

    public void teaAddNotClassLab(List<ArrangeVo> arrangeVoList, List<Lab> typeClassList, Integer weekday) {
        for (Lab lab : typeClassList) {
            ArrangeVo arrangeVo = new ArrangeVo();
            arrangeVo.setWeekday(weekday);
            arrangeVo.setLab(lab);
            arrangeVo.setLabId(lab.getLabId());
            arrangeVo.setTeacherRequest(new TeacherRequest());
            arrangeVoList.add(arrangeVo);
        }
    }
    private void stuAddNOTClassLab(List<ArrangeVo> voList, Lab lab, int weekday) {
        ArrangeVo arrangeVo = new ArrangeVo();
        arrangeVo.setWeekday(weekday);
        arrangeVo.setLab(lab);
        arrangeVo.setLabId(lab.getLabId());
        arrangeVo.setTeacherRequest(new TeacherRequest());
        voList.add(arrangeVo);
    }
    private void stuAddReqClass(List<ArrangeVo> arrangeVoList, StudentRequest s, int weekday) {
        Lab l = (Lab) labService.getByLabId(s.getLabId()).getData();
        ArrangeVo arrangeVo = new ArrangeVo();
        arrangeVo.setWeekday(weekday);
        arrangeVo.setLab(l);
        arrangeVo.setLabId(s.getLabId());
        arrangeVo.setTeacherRequest(new TeacherRequest());
        arrangeVo.getStrings()[s.getSection()]=getStuContent(s);
        arrangeVoList.add(arrangeVo);
    }


}
